﻿using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using MQTTnet;
using MQTTnet.Protocol;
using MQTTnet.Server;
using Newtonsoft.Json;
using Simple.Common.EventBus;
using Simple.Common.Middlewares;
using Simple.Services.MQTT.Model;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace mqtt
{
    public class MqttHostService : IHostedService, IDisposable
    {
        private readonly ILogger _logger;
        private readonly IEventPublisher _eventPublisher;

        public MqttHostService(ILogger<ApiExceptionMiddleware> logger, IEventPublisher eventPublisher)
        {
            _logger = logger;
            _eventPublisher = eventPublisher;

        }

        public void Dispose()
        {

        }
        const string ServerClientId = "SERVER";
        public Task StartAsync(CancellationToken cancellationToken)
        {
            MqttServerOptionsBuilder optionsBuilder = new MqttServerOptionsBuilder();
            optionsBuilder.WithDefaultEndpoint();
            //optionsBuilder.WithDefaultEndpointBoundIPAddress(IPAddress.Parse("127.0.0.1"));
            optionsBuilder.WithDefaultEndpointPort(8290); // 设置 服务端 端口号
            optionsBuilder.WithConnectionBacklog(1000); // 最大连接数
            MqttServerOptions options = optionsBuilder.Build();

            MqttService._mqttServer = new MqttFactory().CreateMqttServer(options);

            MqttService._mqttServer.ClientConnectedAsync += _mqttServer_ClientConnectedAsync; //客户端连接事件
            MqttService._mqttServer.ClientDisconnectedAsync += _mqttServer_ClientDisconnectedAsync; // 客户端关闭事件
            MqttService._mqttServer.ApplicationMessageNotConsumedAsync += _mqttServer_ApplicationMessageNotConsumedAsync; // 消息接收事件

            MqttService._mqttServer.ClientSubscribedTopicAsync += _mqttServer_ClientSubscribedTopicAsync; // 客户端订阅主题事件
            MqttService._mqttServer.ClientUnsubscribedTopicAsync += _mqttServer_ClientUnsubscribedTopicAsync; // 客户端取消订阅事件
            MqttService._mqttServer.StartedAsync += _mqttServer_StartedAsync; // 启动后事件
            MqttService._mqttServer.StoppedAsync += _mqttServer_StoppedAsync; // 关闭后事件
            MqttService._mqttServer.InterceptingPublishAsync += _mqttServer_InterceptingPublishAsync; // 消息接收事件
            MqttService._mqttServer.ValidatingConnectionAsync += _mqttServer_ValidatingConnectionAsync; // 用户名和密码验证有关

            MqttService._mqttServer.StartAsync();
            return Task.CompletedTask;
        }

        /// <summary>
        /// 客户端订阅主题事件
        /// </summary>
        /// <param name="arg"></param>
        /// <returns></returns>
        private Task _mqttServer_ClientSubscribedTopicAsync(ClientSubscribedTopicEventArgs arg)
        {
            // _logger.LogError($"ClientSubscribedTopicAsync：客户端ID=【{arg.ClientId}】订阅的主题=【{arg.TopicFilter}】 ");
            return Task.CompletedTask;
        }

        /// <summary>
        /// 关闭后事件
        /// </summary>
        /// <param name="arg"></param>
        /// <returns></returns>
        private Task _mqttServer_StoppedAsync(EventArgs arg)
        {
            _logger.LogError($"StoppedAsync：MQTT服务已关闭……");
            return Task.CompletedTask;
        }

        /// <summary>
        /// 用户名和密码验证有关
        /// </summary>
        /// <param name="arg"></param>
        /// <returns></returns>
        private Task _mqttServer_ValidatingConnectionAsync(ValidatingConnectionEventArgs arg)
        {
            arg.ReasonCode = MqttConnectReasonCode.Success;
            if ((arg.Username ?? string.Empty) != "admin" || (arg.Password ?? String.Empty) != "admin")
            {
                arg.ReasonCode = MqttConnectReasonCode.Banned;
                _logger.LogError($"ValidatingConnectionAsync：客户端ID=【{arg.ClientId}】用户名或密码验证错误 ");

            }
            return Task.CompletedTask;
        }

        /// <summary>
        /// 消息接收事件
        /// </summary>
        /// <param name="arg"></param>
        /// <returns></returns>
        private Task _mqttServer_InterceptingPublishAsync(InterceptingPublishEventArgs arg)
        {
            if (string.Equals(arg.ClientId, ServerClientId))
            {
                return Task.CompletedTask;
            }
            if (arg.ApplicationMessage.Topic.IndexOf("heartbeat") == -1 && arg.ApplicationMessage.Topic.IndexOf("basic") == -1)
            {
                var rspStr = Encoding.UTF8.GetString(arg.ApplicationMessage.Payload);
                rspStr = rspStr.Replace("Operator", "operator");
                var recPushResult = JsonConvert.DeserializeObject<SnapResult>(rspStr);
                if (recPushResult.Operator != "StrSnapPush" && recPushResult.Operator != "RecPush" && recPushResult.Operator != "CardPush" && recPushResult.Operator != "Ack")
                {
                    _logger.LogError($"InterceptingPublishAsync： Topic主题=【{arg.ApplicationMessage.Topic}】 消息=【{rspStr}】");
                }

                //考勤回调
                if (recPushResult.Operator == "RecPush")
                {
                    var @event1 = new DeviceEventModel();
                    @event1.syncDataQueryModel = null;
                    @event1.ResponseStr = Encoding.UTF8.GetString(arg.ApplicationMessage.Payload);
                    _eventPublisher.PublishAsync(@event1).GetAwaiter().GetResult();
                }
                //同步数据回调
                if (recPushResult.Operator == "EditPersonsNew-Ack")
                {
                    var @event1 = new DeviceEventModel();
                    @event1.IsSyncData = true;
                    @event1.SyncType = 1;
                    @event1.ResponseStr = Encoding.UTF8.GetString(arg.ApplicationMessage.Payload);
                    _eventPublisher.PublishAsync(@event1).GetAwaiter().GetResult();
                }
                if (arg.ApplicationMessage.Topic == "iot/service/deviceid")
                {
                    var @event1 = new DeviceEventModel();
                    @event1.IsSyncData = true;
                    @event1.SyncType = 2;
                    @event1.ResponseStr = Encoding.UTF8.GetString(arg.ApplicationMessage.Payload);
                    _eventPublisher.PublishAsync(@event1).GetAwaiter().GetResult();
                }
            }

            return Task.CompletedTask;

        }

        /// <summary>
        /// 启动后事件
        /// </summary>
        /// <param name="arg"></param>
        /// <returns></returns>
        private Task _mqttServer_StartedAsync(EventArgs arg)
        {
            _logger.LogError($"StartedAsync：MQTT服务已启动……");
            return Task.CompletedTask;
        }

        /// <summary>
        /// 客户端取消订阅事件
        /// </summary>
        /// <param name="arg"></param>
        /// <returns></returns>
        private Task _mqttServer_ClientUnsubscribedTopicAsync(ClientUnsubscribedTopicEventArgs arg)
        {
            // _logger.LogError($"ClientUnsubscribedTopicAsync：客户端ID=【{arg.ClientId}】已取消订阅的主题=【{arg.TopicFilter}】  ");
            return Task.CompletedTask;
        }

        private Task _mqttServer_ApplicationMessageNotConsumedAsync(ApplicationMessageNotConsumedEventArgs arg)
        {
            if (arg.ApplicationMessage.Topic.IndexOf("heartbeat") == -1 && arg.ApplicationMessage.Topic.IndexOf("basic") == -1)
            {
                //var rspStr = Encoding.UTF8.GetString(arg.ApplicationMessage.Payload);
                //rspStr = rspStr.Replace("Operator", "operator");
                //var recPushResult = JsonConvert.DeserializeObject<SnapResult>(rspStr);
                //if (recPushResult.Operator != "StrSnapPush" && recPushResult.Operator != "RecPush")
                //{
                //    _logger.LogError($"ApplicationMessageNotConsumedAsync：Topic主题=【{arg.ApplicationMessage.Topic}】 消息=【{Encoding.UTF8.GetString(arg.ApplicationMessage.Payload)}】 ");
                //}

            }
            return Task.CompletedTask;

        }

        /// <summary>
        /// 客户端断开时候触发
        /// </summary>
        /// <param name="arg"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        private Task _mqttServer_ClientDisconnectedAsync(ClientDisconnectedEventArgs arg)
        {
            var dataStr = JsonConvert.SerializeObject(arg);

            _logger.LogError($"客户端ID=【{arg.ClientId}】已断开  ");
            return Task.CompletedTask;

        }

        /// <summary>
        /// 客户端连接时候触发
        /// </summary>
        /// <param name="arg"></param>
        /// <returns></returns>
        private Task _mqttServer_ClientConnectedAsync(ClientConnectedEventArgs arg)
        {
            _logger.LogError($"客户端ID=【{arg.ClientId}】已连接, 用户名=【{arg.UserName}】地址=【{arg.Endpoint}】  ");
            return Task.CompletedTask;
        }

        public Task StopAsync(CancellationToken cancellationToken)
        {
            return Task.CompletedTask;
        }
    }
}
